package com.zjw.service.message.impl;

import com.zjw.service.message.IConnectSession;
import com.zjw.service.message.IEvent;
import com.zjw.service.message.Message;
import com.zjw.service.message.MessageParser;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

public class SocketConnectSession implements IConnectSession, IEvent {
    byte[] buffer = new byte[1024 * 500];

    private boolean bConnect;
    private final Socket socket;
    private long userId = -1;
    private InputStream inputStream;
    private IConnectListener connectListener;
    private Thread connectThread;

    public SocketConnectSession(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void writeBytes(byte[] bytes) {
        try {
            socket.getOutputStream().write(bytes);
        } catch (IOException e) {
            if (connectListener != null) {
                connectListener.onError(this, e);
            }
        }
    }

    @Override
    public void writeMessage(Message message) {
        try {
            socket.getOutputStream().write(MessageParser.toByte(message));
        } catch (IOException e) {
            if (connectListener != null) {
                connectListener.onError(this, e);
            }
        }
    }

    @Override
    public void disconnect() {
        if (!bConnect) {
            return;
        }
        try {
            bConnect = false;
            socket.close();
            inputStream = null;
            connectThread.interrupt();
        } catch (IOException e) {
            if (connectListener != null) {
                connectListener.onError(this, e);
            }
        }
    }

    @Override
    public void reconnect() {
        if (this.connectListener == null) {
            throw new RuntimeException("invalid reconnect");
        }

        connect(connectListener);
    }

    @Override
    public boolean hasEvent() {
        if (!bConnect) {
            return false;
        }
        int available = 0;
        try {
            available = inputStream.available();
        } catch (IOException e) {
            connectListener.onError(this, e);
            return false;
        }

        return available > 0;
    }

    @Override
    public void notifyEvent() {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            int len = inputStream.read(buffer);
            if (len != -1) {
                outputStream.write(buffer, 0, len);
            }
        } catch (Exception e) {
            connectListener.onError(this, e);
        }
        byte[] bytes = outputStream.toByteArray();
        connectListener.onMessage(this, bytes);
    }

    @Override
    public void connect(IConnectListener connectListener) {
        try {
            this.connectListener = connectListener;
            inputStream = socket.getInputStream();
            bConnect = true;
            connectListener.onConnect(this);
//            connectThread = new Thread(() -> {
//                byte[] buffer = new byte[1024];
//                int len;
//                while (!connectThread.isInterrupted()) {
//                    try {
//                        int available = inputStream.available();
//                        while ((len = inputStream.read(buffer)) != -1) {
//                            connectListener.onMessage(SocketConnectSession.this, Arrays.copyOfRange(buffer, 0, len));
//                        }
//                    } catch (Exception e) {
//                        connectListener.onError(SocketConnectSession.this, e);
//                    }
//                }
//                connectListener.onClose(this);
//            });
//            connectThread.start();
        } catch (IOException e) {
            connectListener.onError(this, e);
        }
    }
}
